package com.zhoutao.blog.seven.service.impl;

import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.zhoutao.blog.seven.dao.model.BookDao;
import com.zhoutao.blog.seven.dao.repository.BookChapterRepository;
import com.zhoutao.blog.seven.dao.repository.BookRepository;
import com.zhoutao.blog.seven.model.converter.BookConverter;
import com.zhoutao.blog.seven.model.detail.BookDetail;
import com.zhoutao.blog.seven.model.response.Book;
import com.zhoutao.blog.seven.service.BookService;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import lombok.var;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;


@Slf4j
@Service
@RequiredArgsConstructor
public class BookServiceImpl implements BookService {

    private final static Cache<String, List<Book>> BOOKS_CACHE =
            CacheBuilder.newBuilder().maximumSize(1).expireAfterWrite(1, TimeUnit.DAYS).build();
    private final static Cache<String, Optional<Book>> BOOK_CACHE =
            CacheBuilder.newBuilder().maximumSize(1).expireAfterWrite(31, TimeUnit.DAYS).build();
    private final BookRepository bookRepository;
    private final BookConverter bookConverter;
    private final BookChapterRepository chapterRepository;

    @Override
    public void cleanCache() {
        BOOKS_CACHE.invalidateAll();
        BOOK_CACHE.invalidateAll();
    }

    @Override
    @SneakyThrows
    public List<BookDetail> list() {
        List<BookDao> books = bookRepository.all();
        if (CollectionUtils.isEmpty(books)) {
            return Collections.emptyList();
        }
        // 查询数量
        var existIds = chapterRepository.findBookIdsOfExistChapter();

        return books.stream().map(bookConverter::converterFrom)
                .map(book -> new BookDetail(book).setHasChapter(existIds.contains(book.getId())))
                .collect(Collectors.toList());

    }

    @Override
    @SneakyThrows
    public Optional<Book> findByKey(String bookKey) {
        return BOOK_CACHE.get(bookKey, () -> {
            log.info("图书缓存已失效,开始从数据库中查询图书:{}", bookKey);
            BookDao bookDao = bookRepository.findByKey(bookKey);
            return Optional.ofNullable(bookDao).map(bookConverter::converterFrom);
        });
    }
}
